package models;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.Page;
import play.data.validation.Constraints;
import play.db.ebean.Model;

/**
 * Modele de la classe Matiere. Une Matière dépend d'un Thème, et peut avoir
 * plusieurs Chapitres.
 * 
 * @author ProjetSI-QCM
 * 
 */
@SuppressWarnings("serial")
@Entity
public class Matiere extends Model {

	/**
	 * Identifiant de la matiere.
	 */
	@Id
	private Long idMatiere;
	/**
	 * Reference vers le Theme de la Matiere.
	 */
	@ManyToOne
	private Theme theme;

	/**
	 * Libelle de la Matiere.Required.
	 */
	@Constraints.Required
	private String libelleM;

	/**
	 * Liste des Chapitres associés à la Matieres.
	 */
	private List<Chapitre> sesChapitres = new ArrayList<Chapitre>();

	/**
	 * Finder de la classe Matiere.
	 */
	private static Finder<Long, Matiere> find = new Finder<Long, Matiere>(
			Long.class, Matiere.class);

	/**
	 * La méthode permet de retrouver une Matiere à partir de son ID.
	 * 
	 * @param id
	 *            Identifiant de la matiere
	 * @return Matiere La matiere
	 */
	public static Matiere findById(final Long id) {
		return Ebean.find(Matiere.class, id);
	}

	/**
	 * Permet de retrouver toutes les Matieres d'un theme donné.
	 * 
	 * @param theme
	 *            Le Theme
	 * @return List<Matiere> Liste des matières associées au thème.
	 */
	public static List<Matiere> findByTheme(final Theme theme) {
		return find.where().eq("theme", theme).findList();
	}

	/**
	 * Retourne toutes les Matières.
	 * 
	 * @return List<Matiere> La liste des Matières.
	 */
	public static List<Matiere> findAll() {
		return find.all();
	}

	/**
	 * Permet de créer un Objet Matiere en Base de Données.
	 * 
	 * @param matiere
	 *            L'objet à créer.
	 */
	public static void create(final Matiere matiere) {
		matiere.save();
	}

	/**
	 * Permet de mettre à jour un Objet Matière en base de Données.
	 * 
	 * @param matiere
	 *            L'objet à mettre à jour.
	 */
	public static void update(final Matiere matiere) {
		matiere.update();
	}

	/**
	 * Permet de Supprimer une Matière de la base de Données.
	 * 
	 * @param id
	 *            L'identifiant de la Matière à supprimer
	 */
	public static void delete(final Long id) {
		Matiere matiere = Matiere.findById(id);
		for (Chapitre chapitre : matiere.getSesChapitres()) {
			Chapitre.delete(chapitre.getIdChapitre());
		}
		find.ref(id).delete();
	}

	/**
	 * Liste des options pour les listes déroulantes.
	 * 
	 * @return Map<String,String>
	 */
	public static Map<String, String> options() {
		final LinkedHashMap<String, String> options = 
				new LinkedHashMap<String, String>();
		for (Matiere c : Matiere.find.orderBy("idMatiere").findList()) {
			options.put(c.getIdMatiere().toString(), c.getLibelleM());
		}
		return options;
	}

	/**
	 * Retourne une Page de Matiere.
	 * 
	 * @param page
	 *            Page à afficher
	 * @param pageSize
	 *            Nombre d'objets par page
	 * @param sortBy
	 *            Propriété utilisée pour le tri
	 * @param order
	 *            Sens du tri (asc ou desc)
	 * @param filter
	 *            Filtre appliqué sur le nom de la colonne
	 * @return Page<Matiere> la page
	 */
	public static Page<Matiere> page(final int page, final int pageSize,
			final String sortBy, final String order, final String filter) {
		return find.where().ilike("idMatiere", "%" + filter + "%")
				.orderBy(sortBy + " " + order).fetch("theme")
				.findPagingList(pageSize).setFetchAhead(false).getPage(page);
	}

	/**
	 * @return the idMatiere
	 */
	public final Long getIdMatiere() {
		return idMatiere;
	}

	/**
	 * @param id
	 *            the idMatiere to set
	 */
	public final void setIdMatiere(final Long id) {
		this.idMatiere = id;
	}

	/**
	 * @return the theme
	 */
	public final Theme getTheme() {
		return theme;
	}

	/**
	 * @param t
	 *            the theme to set
	 */
	public final void setTheme(final Theme t) {
		this.theme = t;
	}

	/**
	 * @return the libelleM
	 */
	public final String getLibelleM() {
		return libelleM;
	}

	/**
	 * @param l
	 *            the libelleM to set
	 */
	public final void setLibelleM(final String l) {
		this.libelleM = l;
	}

	/**
	 * @return the sesChapitres
	 */
	@OneToMany(mappedBy = "matiere", cascade = CascadeType.ALL)
	public final List<Chapitre> getSesChapitres() {
		return sesChapitres;
	}

	/**
	 * @param l
	 *            the sesChapitres to set
	 */
	public final void setSesChapitres(final List<Chapitre> l) {
		this.sesChapitres = l;
	}

}
